package knowledgebase

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"mall/common/enumx"
	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/blog/model"
	"mall/service/blog/rpc/internal/svc"
	"mall/service/blog/rpc/types/blog"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetKBPostListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetKBPostListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetKBPostListLogic {
	return &GetKBPostListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// #24.08.26#  百科列表
func (l *GetKBPostListLogic) GetKBPostList(in *blog.KBPostListReq) (*blog.KBPostListResp, error) {
	if (in.Filter == nil || len(*in.Filter) == 0) && (in.CategoriesId == nil || *in.CategoriesId == 0) {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	preloadMap, eagerLoadMap := modelx.ParsePreloadAndEagerLoad(in.Preload, in.EagerLoad)
	logrus.Info(fmt.Sprintf("GetKBPostsList preloadMap: %+v", preloadMap))

	logrus.Info(fmt.Sprintf("GetKBPostsList eagerLoadMap: %+v", eagerLoadMap))

	kbPostEntityName := model.RpcEntityNames.BlogBook
	_, hasSettingMap := model.RpcEntityPreloadMap[kbPostEntityName]
	if !hasSettingMap {
		return &blog.KBPostListResp{}, nil
	}

	kbPostRepositoryName := model.RepositoryNames.BlogBook
	columnMap, hasColumnMap := model.RepositoryPreloadMap[kbPostRepositoryName]
	if !hasColumnMap {
		return &blog.KBPostListResp{}, nil
	}
	var selectCols []string
	if preloadFields, hasPreloadFields := preloadMap[kbPostEntityName]; hasPreloadFields {
		selectCols = modelx.ParseSelectColumns(preloadFields, columnMap)
	}

	orderBy := modelx.ParseSorter(in.Sorter, columnMap)
	logrus.Info(fmt.Sprintf("GetKBPostsList orderBy: %s", orderBy))
	if len(orderBy) == 0 {
		orderBy = model.BlogKnowledgeBasisColumns.PostModifiedDate + " DESC"
	}
	var (
		res   []*model.BlogKnowledgeBasis
		count int64
		err   error
	)

	//根据类型id查询    调香师  气味家族  品牌
	if in.CategoriesId != nil && *in.CategoriesId > 0 {
		var termRelList []*model.BlogTermRelationship
		termFilterMap := make(map[string]map[string][]any)
		termFilterMap[model.BlogTermRelationshipColumns.TermID] = map[string][]any{
			"equalTo": []any{*in.CategoriesId},
		}

		termRelList, _, err = l.svcCtx.BlogTerm.GetRelationshipList(l.ctx, model.M{
			"offset": (int32(*in.Offset) - 1) * (int32(*in.Limit)),
			"limit":  int32(*in.Limit),
			// "search":  in.Search,
			"select": model.BlogTermRelationshipColumns.ObjectID,
		}, 2, termFilterMap)
		if err != nil || len(termRelList) == 0 {
			return nil, err
		}
		var ids []any
		for _, v := range termRelList {
			ids = append(ids, v.ObjectID)
		}
		kbPostFilterMap := make(map[string]map[string][]any)
		kbPostFilterMap[model.BlogKnowledgeBasisColumns.ID] = map[string][]any{
			"in": ids,
		}
		kbPostFilterMap[model.BlogKnowledgeBasisColumns.PostStatus] = map[string][]any{
			"equalTo": []any{enumx.PostStatusPublish},
		}
		res, count, err = l.svcCtx.BlogBook.GetList(l.ctx, model.M{
			"offset":  in.Offset,
			"limit":   in.Limit,
			"orderBy": orderBy,
			"select":  strings.Join(selectCols, ","),
		}, 1, kbPostFilterMap)
		if err != nil || count == 0 {
			return nil, err
		}
	} else {
		filterMap := modelx.ParseFilter(in.Filter, columnMap)
		logrus.Info(fmt.Sprintf("GetKBPostsList filterMap: %+v", filterMap))
		if filterMap == nil {
			return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
		}
		res, count, err = l.svcCtx.BlogBook.GetList(l.ctx, model.M{
			"offset":  in.Offset,
			"limit":   in.Limit,
			"orderBy": orderBy,
			"select":  strings.Join(selectCols, ","),
		}, 1, filterMap)
		if err != nil || count == 0 {
			return nil, err
		}
	}

	hasNextPage, hasPreviousPage := modelx.ParseCount(count)
	resp := &blog.KBPostListResp{
		HasNextPage:     int32(hasNextPage),
		HasPreviousPage: int32(hasPreviousPage),
	}
	if len(res) > 0 {
		var ids []any
		var idKBPostMap = make(map[uint64]struct{})
		var idTermsMap = make(map[uint64]*blog.BlogCategory)
		var kbPostIdTermMap = make(map[uint64]*blog.BlogCategory)
		for _, v := range res {
			if _, ok := idKBPostMap[v.ID]; ok {
				continue
			}
			ids = append(ids, v.ID)
			idKBPostMap[v.ID] = struct{}{}
		}
		var termIds []any
		var idTermMap = make(map[uint64]struct{})
		termRelFilter := make(map[string]map[string][]any)
		termRelFilter[model.BlogTermRelationshipColumns.ObjectID] = map[string][]any{
			"in": ids,
		}
		termRelList, _, err := l.svcCtx.BlogTerm.GetRelationshipList(l.ctx, model.M{
			"select": model.BlogTermRelationshipColumns.TermID + "," + model.BlogTermRelationshipColumns.ObjectID,
		}, -1, termRelFilter)
		if err != nil {
			return nil, err
		}
		if len(termRelList) > 0 {
			for _, v := range termRelList {
				if _, ok := idTermMap[v.TermID]; ok {
					continue
				}
				termIds = append(termIds, v.TermID)
				idTermMap[v.TermID] = struct{}{}
			}
		}
		termFilter := make(map[string]map[string][]any)
		termFilter[model.BlogTermColumns.TermID] = map[string][]any{
			"in": termIds,
		}
		termSelect := model.BlogTermColumns.Name + "," + model.BlogTermColumns.Slug + "," + model.BlogTermColumns.ParentID
		termList, _, err := l.svcCtx.BlogTerm.GetList(l.ctx, model.M{
			"select": termSelect,
		}, -1, termFilter)
		if err != nil {
			return nil, err
		}
		if len(termList) > 0 {
			for _, v := range termList {
				idTermsMap[v.TermID] = &blog.BlogCategory{
					Id:       int64(v.TermID),
					Name:     v.Name,
					Slug:     v.Slug,
					Uri:      v.Description,
					ParentId: int64(v.ParentID),
				}
			}
		}
		for _, v := range termRelList {
			kbPostIdTermMap[v.ObjectID] = idTermsMap[v.TermID]
		}
		subEntitySettingMap := make(map[string]map[string]*model.ColumnSetting)
		if eagerLoadEntities, hasEagerLoadEntities := eagerLoadMap[kbPostEntityName]; hasEagerLoadEntities {
			for _, entity := range eagerLoadEntities {
				if entitySettingMap, hasEntitySettingMap := model.RpcEntityPreloadMap[entity]; hasEntitySettingMap {
					subEntitySettingMap[entity] = entitySettingMap
				}
			}
		}

		idMediaMap := make(map[uint64][]*blog.BlogMedia)
		blogMediaEntityName := model.RpcEntityNames.BlogMedia
		blogMediaRepositoryName := model.RepositoryNames.BlogMedia
		//WithMedia > 0 查询media
		if in.WithMedia != nil && *in.WithMedia > 0 {
			subPreloadFields, hasSubPreloadFields := preloadMap[blogMediaEntityName]
			subColumnMap, hasSubColumnMap := model.RepositoryPreloadMap[blogMediaRepositoryName]
			if hasSubPreloadFields && hasSubColumnMap {
				var subSelectCols = modelx.ParseSelectColumns(subPreloadFields, subColumnMap)

				mediaFilterMap := make(map[string]map[string][]any)
				mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectID] = map[string][]any{
					"in": ids,
				}
				mediaFilterMap[model.BlogAttachmentRelationshipColumns.ObjectType] = map[string][]any{
					"equalTo": {globalkey.PostTypeKnowledgeBase},
				}

				subSelectCols = append(subSelectCols, model.BlogAttachmentRelationshipColumns.ObjectID)
				var mediaOrderBy = model.BlogAttachmentRelationshipColumns.AttachmentOrder
				mediaList, _, err := l.svcCtx.BlogBook.GetMedia(l.ctx, model.M{
					"orderBy":  mediaOrderBy,
					"pageSize": 3,
					"select":   strings.Join(subSelectCols, ","),
				}, -1, mediaFilterMap)
				if err != nil {
					return nil, err
				}

				if len(mediaList) > 0 {
					for _, v := range mediaList {
						idMediaMap[v.ObjectID] = append(idMediaMap[v.ObjectID], &blog.BlogMedia{
							Uid:       int64(v.AttachmentRelationshipID),
							Id:        int64(v.AttachmentID),
							Uri:       v.AttachmentSource,
							Url:       v.AttachmentImageURL,
							Thumbnail: int32(v.AttachmentThumbnail),
							Order:     int32(v.AttachmentOrder),
							AltText:   v.AttachmentImageAlt,
							Meta:      v.AttachmentImageMeta,
						})
					}
				}
			}
		}
		idMetaMap := make(map[uint64][]*blog.MetaInfo)
		forumPostMetaEntityName := model.RpcEntityNames.BlogBookMeta
		if in.WithMeta != nil && *in.WithMeta > 0 {
			if subPreloadFields, hasSubPreloadFields := preloadMap[forumPostMetaEntityName]; hasSubPreloadFields {
				var metaKeys []any
				for _, field := range subPreloadFields {
					metaKeys = append(metaKeys, field)
				}
				if len(metaKeys) > 0 {
					metaFilterMap := make(map[string]map[string][]any)
					metaFilterMap[model.BlogKnowledgeBaseMetumColumns.KnowledgeBaseID] = map[string][]any{
						"in": ids,
					}
					metaFilterMap[model.BlogKnowledgeBaseMetumColumns.MetaKey] = map[string][]any{
						"in": metaKeys,
					}
					metaList, _, err := l.svcCtx.BlogBook.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
					if err != nil && err != model.ErrNotFound {
						return nil, err
					}

					if len(metaList) > 0 {
						for _, v := range metaList {
							idMetaMap[v.KnowledgeBaseID] = append(idMetaMap[v.KnowledgeBaseID], &blog.MetaInfo{
								Id:    pointy.GetPointer(v.MetaID),
								Key:   pointy.GetPointer(v.MetaKey),
								Value: pointy.GetPointer(v.MetaValue.String),
							})
						}
					}
				}
			}
		}
		for _, v := range res {
			var media []*blog.BlogMedia
			if ms, ok := idMediaMap[v.ID]; ok {
				media = ms[:]
			}
			var viewCount int64
			if ms, ok := idMetaMap[v.ID]; ok {
				if v.ID == 40121 {

					for _, v := range ms {
						if (v.Key != nil && len(*v.Key) > 0) && (v.Value != nil && len(*v.Value) > 0) {
							if *v.Key == "_view_count" {
								viewCount, _ = strconv.ParseInt(*v.Value, 10, 64)
							}
						}

					}
				}
			}
			var Categories *blog.BlogCategory
			if ms, ok := kbPostIdTermMap[v.ID]; ok {
				Categories = ms
			}
			resp.Data = append(resp.Data, &blog.KBPostDetailInfo{
				Id:       pointy.GetPointer(v.ID),
				ParentId: pointy.GetPointer(v.PostParentID),
				AuthorId: pointy.GetPointer(v.PostAuthorID),
				Title:    pointy.GetPointer(v.PostTitle),
				Name:     pointy.GetPointer(v.PostName),
				Excerpt:  pointy.GetPointer(v.PostExcerpt),
				//PicId:           pointy.GetPointer(v.pic),
				//PicUrl:         pointy.GetPointer(v.PostExcerpt),
				//Sort:           pointy.GetPointer(v.PostExcerpt),
				Status:        pointy.GetPointer(uint32(v.PostStatus)),
				CreatedAt:     pointy.GetPointer(modelx.FormatTime(v.PostDate, "")),
				UpdatedAt:     pointy.GetPointer(modelx.FormatTime(v.PostModifiedDate, "")),
				Categories:    Categories,
				CommentStatus: pointy.GetPointer(uint64(v.CommentStatus)),
				MenuOrder:     pointy.GetPointer(uint64(v.MenuOrder)),
				ViewCount:     pointy.GetPointer(uint64(viewCount)),
				Media:         media,
			})
		}
	}
	//resp.Total = uint64(len(resp.List))
	return resp, nil
}
